package com.koalac.ironman.net;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;

import org.apache.http.Header;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.widget.Toast;

import com.foot.travel.activity.LoginActivity;
import com.koalac.ironman.cache.SysAppConfig;
import com.koalac.ironman.net.asynchttpclient.AsyncHttpClient;
import com.koalac.ironman.net.asynchttpclient.AsyncHttpResponseHandler;
import com.koalac.ironman.net.asynchttpclient.MySSLSocketFactory;
import com.koalac.ironman.net.asynchttpclient.RequestParams;
import com.koalac.ironman.net.pojo.request.ClientProtocolBase;
import com.koalac.ironman.net.pojo.response.Response;
import com.koalac.ironman.util.DialogUtils;
import com.koalac.ironman.util.GBLActivityManager;
import com.koalac.ironman.util.StringUtils;
import com.koalac.ironman.util.ToastUtil;
import com.koalac.ironman.widget.LoginDialog;

public class MyRequest {
	private static AsyncHttpClient instance;
	/**
	 * 默认超时时间10秒
	 */
	private static final int DEFAULT_TIME_OUT = 10 * 1000;
	/**
	 * 上传图片的超时时间为30秒
	 */
	private static final int UPLOAD_PHOTO_TIME_OUT = 30 * 1000;

	/**
	 * 授权失败
	 */
	public static final int StatusCodeAuthFailure = 101;
	/**
	 * 需要授权
	 */
	public static final int StatusCodeAuthNeed = 614;

	/**
	 * 获取单例AsyncHttpClient
	 * 
	 * @return
	 */
	public static AsyncHttpClient getHttpClient() {
		if (instance == null) {
			synchronized (MyRequest.class) {
				if (instance == null) {
					instance = new AsyncHttpClient();
					try {
						instance.setSSLSocketFactory(new MySSLSocketFactory(
								null));
					} catch (KeyManagementException e) {

						e.printStackTrace();
					} catch (UnrecoverableKeyException e) {

						e.printStackTrace();
					} catch (NoSuchAlgorithmException e) {

						e.printStackTrace();
					} catch (KeyStoreException e) {

						e.printStackTrace();
					}
				}
			}
		}
		return instance;
	}

	/**
	 * 发送请求(返回http状态码)
	 * 
	 * @param context
	 * @param params
	 *            请求参数
	 * @param callback
	 *            请求成功回调
	 */
	public static void request(final Context context,
			ClientProtocolBase clientProtocolBase,
			final ResponseCallback callback) {
		/**
		 * 请求后台
		 */
		RequestParams params = clientProtocolBase.getArgus(context);
		String address = clientProtocolBase.getAPIddress();
		MyRequest.getHttpClient().setTimeout(DEFAULT_TIME_OUT);
		if (!checkNetWork(context)) {
			Toast.makeText(context, "当前无网络,请检查网络后再试!", Toast.LENGTH_SHORT)
					.show();
			callback.process(false, context, null, "");
			return;
		}
		post(context, address, params, callback);
	}

	/**
	 * 检查是否有网络连接
	 * 
	 * @return
	 */
	public static boolean checkNetWork(Context context) {
		ConnectivityManager connectivityManager = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
		if (networkInfo != null && networkInfo.isConnected()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 统一的post函数
	 * 
	 * @param context
	 * @param address
	 * @param params
	 * @param callback
	 */
	private static void post(final Context context, final String address,
			final RequestParams params, final ResponseCallback callback) {

		getHttpClient().post(address, params, new AsyncHttpResponseHandler() {

			@Override
			public void onProgress(int bytesWritten, int totalSize) {
			}

			@Override
			public void onSuccess(int statusCode, Header[] headers,
					byte[] responseBody) {
				processSuccessResult(context, responseBody, callback, address,
						params);
			}

			@Override
			public void onFailure(int statusCode, Header[] headers,
					byte[] responseBody, Throwable error) {
				processFailureResult(callback, context);
			}
		});
	}

	/**
	 * 统一的post函数
	 * 
	 * @param context
	 * @param address
	 * @param params
	 * @param callback
	 */
	private static void post(final Context context, final String address,
			final RequestParams params, final ResponseProcess responseProcess,
			final ResponseCallback callback) {

		getHttpClient().post(address, params, new AsyncHttpResponseHandler() {

			@Override
			public void onProgress(int bytesWritten, int totalSize) {
				if (totalSize != 0) {
					Log.i("onProgress", ""
							+ ((float) bytesWritten / (float) totalSize));
					responseProcess.onProcess(context, (float) bytesWritten
							/ (float) totalSize);
				}
			}

			@Override
			public void onSuccess(int statusCode, Header[] headers,
					byte[] responseBody) {
				processSuccessResult(context, responseBody, callback, address,
						params);
			}

			@Override
			public void onFailure(int statusCode, Header[] headers,
					byte[] responseBody, Throwable error) {
				processFailureResult(callback, context);
			}
		});
	}

	/**
	 * 处理网络请求失败的结果
	 * 
	 * @param callback
	 * @param context
	 */
	private static void processFailureResult(ResponseCallback callback,
			Context context) {
		/**
		 * 这里要去掉加载框,下拉刷新,下拉加载的UI表现
		 */
		/**
		 * 扩展网络处理失败,方便调用该接口的类对网络请求失败做进一步的处理
		 */
		callback.process(false, context, null, "");

		Toast.makeText(context, "当前网络欠佳,请稍后再试", Toast.LENGTH_SHORT).show();
	}

	/**
	 * 处理网络请求成功的结果
	 * 
	 * @param context
	 * @param responseBody
	 * @param callback
	 * @param address
	 * @param params
	 */
	private static void processSuccessResult(Context context,
			byte[] responseBody, ResponseCallback callback,
			final String address, RequestParams params) {
		Response sBase = new Response(new String(responseBody));
		Log.i("processSuccessResult", address + " " + sBase.getStringForReponse());
		int error = Integer.parseInt(sBase.getError());
		String msg = sBase.getMsg();
		if (!StringUtils.isEmpty(msg)) {
			ToastUtil.toast(context, msg);
		}
		if (responseErrorHandle(context,error)) {
			callback.process(error == 0, context, sBase, msg);
		}else {
		    callback.process(false, context, null, "");
		}
	}

	private static boolean responseErrorHandle(final Context context, int error) {
		if (error == StatusCodeAuthFailure) {
		    /**
		     * 回到登录页面
		     */
		    SysAppConfig.getInstance().clearClientConfig(context);
		    GBLActivityManager.getActivityManager().popAllActivityExceptOne(null);
		    context.startActivity(new Intent(context,LoginActivity.class));
			return false;
		}
		if (error == StatusCodeAuthNeed) {
		DialogUtils.createConfirmDialog(context, "", "该功能需要登录", "前往登录页面", "取消", new OnClickListener(){
		    @Override
		    public void onClick(DialogInterface dialog, int which) {
			context.startActivity(new Intent(context,LoginActivity.class));
			dialog.dismiss();
		    }
		},new OnClickListener() {
		    
		    @Override
		    public void onClick(DialogInterface dialog, int which) {
			dialog.dismiss();
		    }
		}, DialogUtils.NO_ICON, true).show();
		
		    return false;
		}
		return true;
	}

	/**
	 * 上传单张图片 inputStream
	 * 
	 * @param fileList
	 * @throws FileNotFoundException
	 */
	public static void upload(ByteArrayOutputStream baos, String fileName,
			final Context context, ClientProtocolBase clientProtocolBase,
			final ResponseProcess responseProcess,
			final ResponseCallback callback) {
		/**
		 * 无网络时的UI表现
		 */
		if (!checkNetWork(context)) {
			Toast.makeText(context, "当前无网络,请检查网络后再试!", Toast.LENGTH_SHORT)
					.show();
			callback.process(false, context, null, "");
			return;
		}
		/**
		 * 设置上传一张图片的超时时间为30s
		 */
		MyRequest.getHttpClient().setTimeout(UPLOAD_PHOTO_TIME_OUT);
		RequestParams params = clientProtocolBase.getArgus(context);
		String address = clientProtocolBase.getAPIddress();
		ByteArrayInputStream inputStream = new ByteArrayInputStream(
				baos.toByteArray());
		params.put("Filedata", inputStream, fileName);
		post(context, address, params, responseProcess, callback);
	}

}
